﻿using PCLCrypto;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SampleApp
{
    class MyEncryptor : FileDbNs.IEncryptor
    {
        string _password;
        byte[] _salt;

        internal MyEncryptor( string password, byte[] salt )
        {
            _password = password;
            _salt = salt;
        }

        #region IEncryptor

        public byte[] Encrypt( byte[] dataToEncrypt )
        {
            return Encrypt( dataToEncrypt, _password, _salt );
        }

        public byte[] Decrypt( byte[] encryptedData )
        {
            return Decrypt( encryptedData, _password, _salt );
        }
        #endregion IEncryptor

        #region PclCrypto

        /// <summary>    
        /// Creates Salt with given length in bytes.    
        /// </summary>    
        /// <param name="lengthInBytes">No. of bytes</param>    
        /// 
        internal static byte[] CreateSalt( uint lengthInBytes )
        {
            return WinRTCrypto.CryptographicBuffer.GenerateRandom( lengthInBytes );
        }

        /// <summary>    
        /// Creates a derived key from a comnination     
        /// </summary>    
        /// <param name="password"></param>    
        /// <param name="salt"></param>    
        /// <param name="keyLengthInBytes"></param>    
        /// <param name="iterations"></param>    
        /// 
        internal static byte[] CreateDerivedKey( string password, byte[] salt, int keyLengthInBytes = 32, int iterations = 1000 )
        {
            byte[] key = NetFxCrypto.DeriveBytes.GetBytes( password, salt, iterations, keyLengthInBytes );
            return key;
        }

        /// <summary>    
        /// Encrypts given data using symmetric algorithm AES    
        /// </summary>    
        /// <param name="data">Data to encrypt</param>    
        /// <param name="password">Password</param>    
        /// <param name="salt">Salt</param>    
        /// <returns>Encrypted bytes</returns>    
        /// 
        internal static byte[] Encrypt( byte[] data, string password, byte[] salt )
        {
            byte[] key = CreateDerivedKey( password, salt );

            ISymmetricKeyAlgorithmProvider aes = WinRTCrypto.SymmetricKeyAlgorithmProvider.OpenAlgorithm( SymmetricAlgorithm.AesCbcPkcs7 );
            ICryptographicKey symetricKey = aes.CreateSymmetricKey( key );
            var bytes = WinRTCrypto.CryptographicEngine.Encrypt( symetricKey, data );
            return bytes;
        }
        /// <summary>    
        /// Decrypts given bytes using symmetric alogrithm AES    
        /// </summary>    
        /// <param name="data">data to decrypt</param>    
        /// <param name="password">Password used for encryption</param>    
        /// <param name="salt">Salt used for encryption</param>    
        /// <returns>Dencrypted bytes</returns>    
        /// 
        internal static byte[] Decrypt( byte[] data, string password, byte[] salt )
        {
            byte[] key = CreateDerivedKey( password, salt );

            ISymmetricKeyAlgorithmProvider aes = WinRTCrypto.SymmetricKeyAlgorithmProvider.OpenAlgorithm( SymmetricAlgorithm.AesCbcPkcs7 );
            ICryptographicKey symetricKey = aes.CreateSymmetricKey( key );
            var bytes = WinRTCrypto.CryptographicEngine.Decrypt( symetricKey, data );
            return bytes;
        }
        #endregion PclCrypto
    }
}
